#include "EliteGuard.h"
#include "BehaviorManager.h"
#include "BaseBehavior.h"
#include "../SGD Wrappers/SGD_GraphicsManager.h"
#include "GameplayState.h"
#include "Player.h"
#include "CreateBulletMessage.h"
#include "../SGD Wrappers/SGD_Event.h"
#include "SpawnDoor.h"
#include "Graph.h"
#include "DestroyObjectMessage.h"

/*virtual*/ void EliteGuard::Update(float dt)	 /*override*/
{
	if (isAlive)
	{
		if (m_tStunTimer.Update(dt))
		{
			if (currBehavior != nullptr)
			{
				if (m_nAIState == PATROL)
				{
					if (currBehavior->Update(dt, this, *navGraph->GetVertexElement(currPath[m_nCurrPathNode])))
					{
						m_nCurrPathNode++;
						if (m_nCurrPathNode == currPath.size())
						{
							m_nCurrPathNode = 0;
							m_nCurrWaypoint++;
							if (m_nCurrWaypoint == m_vWayPoints.size())
								m_nCurrWaypoint = 0;

							navGraph->FindPath(m_vWayPoints[m_nCurrWaypoint], homeNode, currPath);
							m_nAIState = GO_HOME;
						}
					}
				}

				else if (m_nAIState == SEARCHING)
				{
					if (currBehavior->Update(dt, this, *navGraph->GetVertexElement(currPath[m_nCurrPathNode])))
					{
						m_nCurrPathNode++;
						if (m_nCurrPathNode == currPath.size())
						{
							m_nCurrPathNode = 0;
							m_nCurrWaypoint++;
							if (m_nCurrWaypoint == m_vWayPoints.size())
								m_nCurrWaypoint = 0;
							unsigned int closestNodeToMe;

							float distanceToNode = 70000;
							float distanceToLastKnown = 70000;
							for (unsigned int i = 0; i < navGraph->size(); i++)
							{

								SGD::Point temp = *navGraph->GetVertexElement(i);
								float newDistance = (temp - m_ptPosition).ComputeLength();

								if (newDistance < distanceToNode)
								{
									distanceToNode = newDistance;
									closestNodeToMe = i;
								}

							}
							navGraph->FindPath(closestNodeToMe, m_vWayPoints[m_nCurrWaypoint], currPath);
							m_nAIState = PATROL;
						}
					}
				}

				else if (m_nAIState == ALERT)
					currBehavior->Update(dt, this, m_pTarget->GetPosition());

				else if (m_nAIState == GO_HOME)
				{
					if (currBehavior->Update(dt, this, *navGraph->GetVertexElement(currPath[m_nCurrPathNode])))
					{
						m_nCurrPathNode++;
						if (m_nCurrPathNode == currPath.size())
						{

							DestroyObjectMessage* dMsg = new DestroyObjectMessage{ this };

							dMsg->QueueMessage();
							dMsg = nullptr;
						}
					}
				}

			}
			EnemyUnit::Update(dt);
		}
	}
	
	
}

/*virtual*/ void EliteGuard::HandleEvent(const SGD::Event* pEvent)
{
	if (isAlive)
	{
		if (pEvent->GetEventID() == "LOST_TARGET")
		{
			m_ptLastKnownPos = m_pTarget->GetPosition();
			unsigned int closestNodeToMe;
			unsigned int closestNodeToPlayer;

			float distanceToNode = 70000;
			float distanceToLastKnown = 70000;
			for (unsigned int i = 0; i < navGraph->size(); i++)
			{

				SGD::Point temp = *navGraph->GetVertexElement(i);
				float newDistance = (temp - m_ptPosition).ComputeLength();

				if (newDistance < distanceToNode)
				{
					distanceToNode = newDistance;
					closestNodeToMe = i;
				}

			}

			for (unsigned int i = 0; i < navGraph->size(); i++)
			{

				SGD::Point temp = *navGraph->GetVertexElement(i);
				float newDistance = (temp - m_ptLastKnownPos).ComputeLength();

				if (newDistance < distanceToLastKnown)
				{
					distanceToLastKnown = newDistance;
					closestNodeToPlayer = i;
				}

			}

			m_nAIState = SEARCHING;
			navGraph->FindPath(closestNodeToMe, closestNodeToPlayer, currPath);
			m_nCurrPathNode = 0;

			RetrieveBehavior("runTo");
		}



		else if (pEvent->GetEventID() == "TARGET_FOUND")
		{
			m_nAIState = ALERT;
			RetrieveBehavior("hostile");

		}

		else if (pEvent->GetEventID() == "STUNNED")
		{
			m_tStunTimer.AddTime(5.0f);
			unsigned int closestNodeToMe;
			unsigned int closestNodeToPlayer;

			float distanceToNode = 70000;
			float distanceToLastKnown = 70000;
			for (unsigned int i = 0; i < navGraph->size(); i++)
			{

				SGD::Point temp = *navGraph->GetVertexElement(i);
				float newDistance = (temp - m_ptPosition).ComputeLength();

				if (newDistance < distanceToNode)
				{
					distanceToNode = newDistance;
					closestNodeToMe = i;
				}

			}

			for (unsigned int i = 0; i < navGraph->size(); i++)
			{

				SGD::Point temp = *navGraph->GetVertexElement(i);
				float newDistance = (temp - m_ptLastKnownPos).ComputeLength();

				if (newDistance < distanceToLastKnown)
				{
					distanceToLastKnown = newDistance;
					closestNodeToMe = i;
				}

			}

			m_nAIState = SEARCHING;
			navGraph->FindPath(closestNodeToMe, closestNodeToPlayer, currPath);
			m_nCurrPathNode = 0;

			RetrieveBehavior("runTo");

		}
		else if (pEvent->GetEventID() == "ALARM_OFF")
		{
			unsigned int closestNodeToMe;
			float distanceToNode = 70000;
			for (unsigned int i = 0; i < navGraph->size(); i++)
			{

				SGD::Point temp = *navGraph->GetVertexElement(i);
				float newDistance = (temp - m_ptPosition).ComputeLength();

				if (newDistance < distanceToNode)
				{
					distanceToNode = newDistance;
					closestNodeToMe = i;
				}

			}
			navGraph->FindPath(closestNodeToMe, homeNode, currPath);

			m_nAIState = GO_HOME;
			RetrieveBehavior("move");

		}
	}
		

}
/*virtual*/ void EliteGuard::HandleCollision(const IBase* pOther) /*override*/
{
	if (isAlive)
	{
		if (pOther->GetType() == OBJ_PLAYER)
		{
			if (dynamic_cast<const Player*>(pOther)->GetAttackState() == 0)
			{
				m_nAIState = ALERT;
				RetrieveBehavior("hostile");
			}
			else
			{
				SGD::Vector toTarget = (m_pTarget->GetPosition() - m_ptPosition);

				if (direction.ComputeAngle(toTarget) > 0.20f)
				{
					isAlive = false;
				}
			}


		}
		else if (pOther->GetType() == OBJ_TRIGGER || pOther->GetType() == OBJ_PLAYERCOLLISION)
		{

		}
		else
			MovingObject::HandleCollision(pOther);
	}
	
}
/*virtual*/ void EliteGuard::Attack() /*override*/
{
	m_tShotTimer.AddTime(1.0f);
	CreateBulletMessage* pMsg = new CreateBulletMessage(this);
	pMsg->QueueMessage();
	pMsg = nullptr;
}

void EliteGuard::SetOwner(SpawnDoor* owner)
{
	if (m_pOwner != nullptr)
	{
		m_pOwner->Release();
		m_pOwner = nullptr;
	}
	m_pOwner = owner;
}
